package com.iot.ammeter.service.impl.web.campus;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.iot.ammeter.constant.Constant;
import com.iot.ammeter.dto.web.campus.RoomDTO;
import com.iot.ammeter.entity.web.campus.Room;
import com.iot.ammeter.entity.web.equipment.EquipmentManagement;
import com.iot.ammeter.entity.web.equipment.EquipmentModel;
import com.iot.ammeter.exception.BusinessExceptions;
import com.iot.ammeter.mapper.web.campus.RoomMapper;
import com.iot.ammeter.mapper.web.equipment.EquipmentManagementMapper;
import com.iot.ammeter.mapper.web.equipment.EquipmentModelMapper;
import com.iot.ammeter.query.web.campus.RoomQuery;
import com.iot.ammeter.service.web.campus.RoomService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iot.ammeter.utils.SnowFlakeIdWorker;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 房间表 服务实现类
 * </p>
 *
 * @author basil
 * @since 2021-09-25
 */
@Service
public class RoomServiceImpl extends ServiceImpl<RoomMapper, Room> implements RoomService {

    private final SnowFlakeIdWorker snowFlakeIdWorker;
    private final RoomMapper roomMapper;
    private final EquipmentModelMapper equipmentModelMapper;
    private final EquipmentManagementMapper equipmentManagementMapper;

    public RoomServiceImpl(SnowFlakeIdWorker snowFlakeIdWorker, RoomMapper roomMapper, EquipmentModelMapper equipmentModelMapper, EquipmentManagementMapper equipmentManagementMapper) {
        this.snowFlakeIdWorker = snowFlakeIdWorker;
        this.roomMapper = roomMapper;
        this.equipmentModelMapper = equipmentModelMapper;
        this.equipmentManagementMapper = equipmentManagementMapper;
    }

    /**
     * 添加房间信息
     * <p>
     * 1获取房间基本数据
     * 2获取设备型号 ——>查询设备型号的数量 ，不存在添加房间失败
     * 3获取设备唯一识别码 ->设备型号对应id，识别码插入tb_equipment_management中
     *
     * @param roomDTO 房间信息
     * @return 添加成功或者失败
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String addRoom(RoomDTO roomDTO) {
        /**
         * 数据校验
         */
        String buildingId = roomDTO.getBuildingId().trim();
        String equipmentIdentifier = roomDTO.getEquipmentIdentifier().trim();
        String roomNumber = roomDTO.getRoomNumber().trim();
        String equipmentModel = roomDTO.getEquipmentModel().trim();
        if (StringUtils.isEmpty(buildingId)) {
            throw new BusinessExceptions("楼栋id不能为空");
        }
        if (StringUtils.isEmpty(equipmentIdentifier)) {
            throw new BusinessExceptions("设备id不能为空");
        }
        if (StringUtils.isEmpty(roomNumber)) {
            throw new BusinessExceptions("房间号不能为空");
        }
        /**
         * 设备是否绑定
         */
        if (roomMapper.selectCount(new LambdaQueryWrapper<Room>().eq(Room::getEquipmentIdentifier, equipmentIdentifier)) != 0) {
            throw new BusinessExceptions("此设备已绑定");
        }
        /**
         * 检查安装数量
         */
        EquipmentModel number = equipmentModelMapper.selectOne(new LambdaQueryWrapper<EquipmentModel>().eq(EquipmentModel::getEquipmentModel, equipmentModel));
        if (number == null) {
            throw new BusinessExceptions("设备型号不存在");
        }
        int equipmentNumber = number.getEquipmentNumber();
        int installedNumber = number.getInstalledNumber();
        String equipmentModelId = number.getEquipmentModelId();
        if (equipmentNumber <= installedNumber) {
            throw new BusinessExceptions("该设备型号安装数量已满");
        }
        /**
         * 房间是否存在
         */
        LambdaQueryWrapper<Room> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Room::getRoomNumber, roomNumber).eq(Room::getBuildingId, buildingId);
        if (roomMapper.selectOne(lambdaQueryWrapper) != null) {
            throw new BusinessExceptions("房间已存在");
        }
        /**
         * 补全数据
         */
        String roomId = String.valueOf(snowFlakeIdWorker.nextId());
        Room roomToDb = new Room();
        roomToDb.setRoomId(roomId);
        roomToDb.setRoomNumber(roomNumber);
        roomToDb.setStatus(Constant.Room.IDLE);
        roomToDb.setCreateTime(LocalDateTime.now());
        roomToDb.setUpdateTime(LocalDateTime.now());
        roomToDb.setEquipmentIdentifier(equipmentIdentifier);
        roomToDb.setRemark(roomDTO.getRemark());
        roomToDb.setBuildingId(buildingId);
        /**
         * 保存至数据库
         */
        int i = roomMapper.insert(roomToDb);
        if (i != 1) {
            throw new BusinessExceptions("房间信息添加失败");
        }
        /**
         * 更新设备型号表已安装数量
         */
        number.setEquipmentModelId(equipmentModelId);
        number.setInstalledNumber(installedNumber + 1);
        number.setUpdateTime(LocalDateTime.now());
        int result = equipmentModelMapper.updateById(number);

        /**
         * 将数据插入电表管理表中
         */
        EquipmentManagement equipmentManagementToDb = new EquipmentManagement();
        equipmentManagementToDb.setEquipmentIdentifier(equipmentIdentifier);
        //equipmentManagementToDb.setEquipmentModelId(number.getEquipmentModelId());
        equipmentManagementToDb.setEquipmentStatus(Constant.EquipmentManagement.ON_LINE_STATUS);
        equipmentManagementToDb.setIsEnable(Constant.EquipmentManagement.IS_NO_ENABLE);
        equipmentManagementToDb.setDegree(new BigDecimal(0.0));
        equipmentManagementToDb.setShutDown(Constant.EquipmentManagement.IS_POWER_ON);
        equipmentManagementToDb.setCreateTime(LocalDateTime.now());
        equipmentManagementToDb.setUpdateTime(LocalDateTime.now());
        result += equipmentManagementMapper.insert(equipmentManagementToDb);
        return result > 1 ? "添加房间信息成功" : "添加房间信息失败";
    }

    /**
     * 编辑房间信息
     *
     * @param roomId  房间id
     * @param roomDTO 房间信息
     * @return 编辑成功或者编辑失败提示
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String editRoom(String roomId, RoomDTO roomDTO) {
        /**
         * 实体校验
         */
        if (StringUtils.isEmpty(roomId)) {
            return "房间id不能为空";
        }
        String buildingId = roomDTO.getBuildingId().trim();
        String equipmentIdentifier = roomDTO.getEquipmentIdentifier().trim();
        String roomNumber = roomDTO.getRoomNumber().trim();
        if (StringUtils.isEmpty(buildingId)) {
            throw new BusinessExceptions("楼栋id不能为空");
        }
        if (StringUtils.isEmpty(equipmentIdentifier)) {
            throw new BusinessExceptions("设备id不能为空");
        }
        if (StringUtils.isEmpty(roomNumber)) {
            throw new BusinessExceptions("房间号不能为空");
        }
        /**
         * 房间是否存在
         */
        Room roomFromDb = roomMapper.selectById(roomId);
        if (roomFromDb == null) {
            throw new BusinessExceptions("房间信息不存在");
        }
        /**
         * 房间名是否存在
         */
        LambdaQueryWrapper<Room> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Room::getRoomNumber, roomNumber).eq(Room::getBuildingId, buildingId).or().eq(Room::getRoomId, roomId);
        if (roomMapper.selectCount(lambdaQueryWrapper) != 1) {
            throw new BusinessExceptions("房间名已存在");
        }
        /**
         * 补全数据
         */
        roomFromDb.setRoomNumber(roomNumber);
        roomFromDb.setStatus(roomDTO.getEquipmentStatus());
        roomFromDb.setUpdateTime(LocalDateTime.now());
        roomFromDb.setEquipmentIdentifier(equipmentIdentifier);
        roomFromDb.setRemark(roomDTO.getRemark());
        roomFromDb.setBuildingId(buildingId);
        int result = roomMapper.updateById(roomFromDb);
        return result > 0 ? "更新房间信息成功" : "更新房间信息失败";
    }

    /**
     * 获得房间信息列表
     *
     * @param page      请求页码
     * @param pageSize  每页数量
     * @param roomQuery 房间查询条件
     * @return ResponseResult
     */
    @Override
    public IPage<RoomDTO> getRoomList(int page, int pageSize, RoomQuery roomQuery) {
        /**
         * 封装page对象
         */
        Page<RoomDTO> pages = new Page<>(page, pageSize);
        IPage<RoomDTO> iPage = roomMapper.listRooms(pages, roomQuery);
        return iPage;
    }

    /**
     * 批量添加房间信息
     *
     * @param roomDTO 房间信息
     * @return 返回批量添加成功或者失败提示
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String batchAddRoom(RoomDTO roomDTO) {
        /**
         * 数据校验
         */

        String buildingId = roomDTO.getBuildingId().trim();
        List<String> roomNames = roomDTO.getRoomNames();
        if (StringUtils.isEmpty(buildingId)) {
            throw new BusinessExceptions("楼栋id不能为空");
        }
        if (roomNames.isEmpty()) {
            throw new BusinessExceptions("房间号不能为空");
        }


        LambdaQueryWrapper<Room> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Room::getBuildingId, buildingId);
        /**
         * 创建房间集合
         */
        List<Room> rooms = new ArrayList<>();
        Room roomToDb = null;
        for (String romName : roomNames) {
            roomToDb = new Room();
            roomToDb.setRoomId(String.valueOf(snowFlakeIdWorker.nextId()));
            roomToDb.setRoomNumber(romName);
            roomToDb.setStatus(Constant.Room.IDLE);
            roomToDb.setCreateTime(LocalDateTime.now());
            roomToDb.setUpdateTime(LocalDateTime.now());
            roomToDb.setEquipmentIdentifier(null);
            roomToDb.setBuildingId(buildingId);
            roomToDb.setRemark(romName);
            rooms.add(roomToDb);
            lambdaQueryWrapper.eq(Room::getRoomNumber, romName);
        }
        /**
         * 房间是否存在
         */
        if (roomMapper.selectCount(lambdaQueryWrapper) > 0) {
            throw new BusinessExceptions("房间已存在");
        }

        /**
         * 保存至数据库
         */
        int result = roomMapper.insertBatchSomeColumn(rooms);
        return result > 0 ? "批量添加成功" : "批量添加失败";
    }

    /**
     * 删除/批量删除房间
     *
     * @param roomIds 房间id数组
     * @return 删除成功或者失败提示
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer batchDelRoom(String[] roomIds) {
        int result = roomMapper.deleteBatchIds(Arrays.asList(roomIds));
        return result;
    }

    /**
     * 按查询条件获取全部房间
     *
     * @param roomQuery 查询条件
     * @return 所有房间集合
     */
    @Override
    public List<RoomDTO> exportRoomList(RoomQuery roomQuery) {
        Page<RoomDTO> pages = new Page<>();
        IPage<RoomDTO> iPage = roomMapper.listRooms(pages, roomQuery);
        return iPage.getRecords();
    }
}
